home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / oldwish / wishHandlers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-01-23  |  27.4 KB  |  979 lines

  1. /* 
  2.  * wishHandlers.c --
  3.  *
  4.  *    Event handlers and such for flat display.
  5.  *
  6.  * Copyright 1987 Regents of the University of California
  7.  * All rights reserved.
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /a/newcmds/wish/RCS/wishHandlers.c,v 1.4 89/01/11 11:32:00 mlgray Exp Locker: mgbaker $ SPRITE (Berkeley)";
  19. #endif not lint
  20.  
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include "string.h"
  24. #include "util.h"
  25. #include "monitorClient.h"
  26. #include "wishInt.h"
  27.  
  28. extern    char    wishStartUp[];
  29.  
  30.  
  31. /*
  32.  *----------------------------------------------------------------------
  33.  *
  34.  * WishToggleSelection --
  35.  *
  36.  *    Toggle the selection status of an entry.  The event was selected in
  37.  *    the display window, but we are passed the surrounding window.
  38.  *
  39.  * Results:
  40.  *    None.
  41.  *
  42.  * Side effects:
  43.  *    If the coordinates are those of an entry, it is selected if it
  44.  *    wasn't already selected and it is de-selected if it was already
  45.  *    selected.
  46.  *
  47.  *----------------------------------------------------------------------
  48.  */
  49. void
  50. WishToggleSelection(window, eventPtr, lineP)
  51.     Window            window;
  52.     XButtonPressedEvent        *eventPtr;
  53.     Boolean            lineP;        /* double click for a line? */
  54. {
  55.     short    x, y;
  56.     WishWindow    *aWindow;
  57.     char    buffer[100];
  58.  
  59.     if (eventPtr->type != ButtonPress && eventPtr->type != ButtonRelease) {
  60.     return;
  61.     }
  62.  
  63.     if (XFindContext(wishDisplay, window, wishWindowContext,
  64.     (caddr_t) &aWindow) != 0) {
  65.     Sx_Panic(wishDisplay, "Wish didn't recognize given window.");
  66.     }
  67.  
  68.     /* the event was selected in the display window, so coordinates are ok */
  69.     x = ((XButtonEvent *) eventPtr)->x;
  70.     y = ((XButtonEvent *) eventPtr)->y;
  71.  
  72.     sprintf(buffer, "toggleSelection %d %d %d", x, y, lineP);
  73.  
  74.     (void) WishDoCmd(aWindow, buffer);
  75.  
  76.     return;
  77. }
  78.  
  79.  
  80. /*
  81.  *----------------------------------------------------------------------
  82.  *
  83.  * WishEditRule --
  84.  *
  85.  *    The user has typed something inside a group header entry window.
  86.  *    If he has typed a carriage return, then I take the new string and
  87.  *    try to make it the new selection rule for the window.  If there's
  88.  *    something wrong with the new rule, I tell the user and put back the
  89.  *    old rule. If the rule is ok, I ask him (or will do this soon) whether
  90.  *    he wants to make this rule permanent (put it in his .wish file).
  91.  *    Either way, I go and reselect stuff according to the new rule. For now
  92.  *    I do this the dumb way (I don't just redo the particular group --
  93.  *    I redo all groups), but I'll change it if it's too slow.
  94.  *
  95.  * Results:
  96.  *    None.
  97.  *
  98.  * Side effects:
  99.  *    Many.  Perhaps a new rule set, newly selected files, an edited .wish,
  100.  *    and a newly built display.
  101.  *
  102.  *----------------------------------------------------------------------
  103.  */
  104. void
  105. WishEditRule(window, eventPtr)
  106.     Window    window;
  107.     XKeyPressedEvent    *eventPtr;
  108. {
  109.     WishWindow    *aWindow;
  110.     WishGroup        *groupPtr;
  111.     Boolean        editRuleP = FALSE;
  112.     char        *mapping;
  113.     char        keyString[20];
  114.     int            length;
  115.     char        *buffer;
  116.  
  117. fprintf(stderr, "WishEditRule called\n");
  118.     if (eventPtr->type != KeyPress && eventPtr->type != KeyRelease) {
  119.     return;
  120.     }
  121. fprintf(stderr, "In WishEditRule.  event was KeyPress or Release.\n");
  122.     if (XFindContext(wishDisplay, window, wishWindowContext,
  123.         (caddr_t) &aWindow) != 0) {
  124.     Sx_Panic(wishDisplay, "Wish didn't recognize given window.");
  125.     }
  126.     if (XFindContext(wishDisplay, window, wishGroupWindowContext,
  127.         (caddr_t) &groupPtr) != 0) {
  128.     Sx_Panic(wishDisplay, "Wish didn't recognize given header window.");
  129.     }
  130.     /* Check to see if they've typed a carriage return. */
  131.     length = XLookupString(eventPtr, keyString, 20, (KeySym *) NULL,
  132.         (XComposeStatus *) NULL);
  133.     
  134.     /* John does stuff here to force ctrl chars and meta bits.  Should I? */
  135.     for (mapping = keyString; length > 0; length--) {
  136.     if (*mapping++ == ctrl('m')) {
  137.         editRuleP = TRUE;
  138.         break;
  139.     }
  140.     }
  141.     if (editRuleP == FALSE) {
  142.     return;
  143.     }
  144.     if (groupPtr->defType != COMPARISON) {
  145.     sprintf(wishErrorMsg, "%s %s %s.", "Currently it is only possible to",
  146.         "edit the rules graphically for groups defined",
  147.         "with simple comparisons");
  148.     aWindow->notifierP = TRUE;
  149.     Sx_Notify(wishDisplay, aWindow->displayWindow, -1, -1, 0,
  150.         wishErrorMsg, NULL, TRUE, "Continue", NULL);
  151.     aWindow->notifierP = FALSE;
  152.     /* restore header */
  153.     strcpy(groupPtr->editHeader, groupPtr->rule);
  154.     Sx_EntryMake(wishDisplay, groupPtr->headerWindow,
  155.         aWindow->surroundingWindow, NULL,
  156.         aWindow->fontPtr, aWindow->foreground, aWindow->background,
  157.         groupPtr->editHeader, sizeof (groupPtr->editHeader));
  158.     return;
  159.     }
  160.     
  161.     buffer = (char *) malloc(strlen("changeGroup") + strlen(groupPtr->rule) +
  162.         strlen("comparison") + strlen(groupPtr->editHeader) + 4); 
  163.  
  164.     sprintf(buffer, "changeGroup %s %s %s", groupPtr->rule,
  165.         "comparison", groupPtr->editHeader);
  166.  
  167.     if (WishDoCmd(aWindow, buffer) != TCL_OK) {
  168.     /* restore header */
  169.     strcpy(groupPtr->editHeader, groupPtr->rule);
  170.     Sx_EntryMake(wishDisplay, groupPtr->headerWindow,
  171.         aWindow->surroundingWindow, NULL,
  172.         aWindow->fontPtr, aWindow->foreground, aWindow->background,
  173.         groupPtr->editHeader, sizeof (groupPtr->editHeader));
  174.     }
  175.  
  176.     free(buffer);
  177.  
  178.     return;
  179. }
  180.  
  181.  
  182.  
  183. /*
  184.  *----------------------------------------------------------------------
  185.  *
  186.  * WishEditDir --
  187.  *
  188.  *    The user has typed something in the directory name window.  If he
  189.  *    has typed a carriage return, then I look at the edited string and try to
  190.  *    make it the new dir of the display.  If the string isn't a valid
  191.  *    file or directory, then we notify them, and redisplay the current
  192.  *    dir. If a proper node has been chosen, call WishChangeDir() with it.
  193.  *    The event was selected in the title window, but the window we
  194.  *    are passed is the surrounding window.
  195.  *
  196.  * Results:
  197.  *    None.
  198.  *
  199.  * Side effects:
  200.  *    If a good dir was selected, it becomes the new dir of the display
  201.  *    and we redisplay.
  202.  *
  203.  *----------------------------------------------------------------------
  204.  */
  205. void
  206. WishEditDir(window, eventPtr)
  207.     Window        window;
  208.     XKeyPressedEvent    *eventPtr;
  209. {
  210.     struct    stat    dirAtts;
  211.     WishWindow    *aWindow;
  212.     int            length;
  213.     Boolean        editDirP = FALSE;
  214.     char        *mapping;
  215.     char        keyString[20];
  216.  
  217.     if (eventPtr->type != KeyPress && eventPtr->type != KeyRelease) {
  218.     return;
  219.     }
  220.     if (XFindContext(wishDisplay, window, wishWindowContext,
  221.         (caddr_t) &aWindow) != 0) {
  222.     Sx_Panic(wishDisplay, "Wish didn't recognize a given window.");
  223.     }
  224.     /* Check to see if they've typed a carriage return. */
  225.     length = XLookupString(eventPtr, keyString, 20, (KeySym *) NULL,
  226.         (XComposeStatus *) NULL);
  227.     /* John does stuff here to force ctrl chars and meta bits.  Should I? */
  228.     for (mapping = keyString; length > 0; length--) {
  229.     if (*mapping++ == ctrl('m')) {
  230.         editDirP = TRUE;
  231.         break;
  232.     }
  233.     }
  234.     if (editDirP == FALSE) {
  235.     return;
  236.     }
  237.     /*
  238.      * Put new dir name into canonical form.  If this fails, something is
  239.      * wrong with the new name and we restore the current good one in
  240.      * the title window.
  241.      */
  242.     if (Util_CanonicalDir(aWindow->editDir, aWindow->dir, aWindow->editDir) ==
  243.         NULL) {
  244.     /* error message returned in aWindow->editDir */
  245.     aWindow->notifierP = TRUE;
  246.     Sx_Notify(wishDisplay, aWindow->surroundingWindow, -1, -1, 0,
  247.         aWindow->editDir, NULL, TRUE, "Skip command", (char *) NULL);
  248.     aWindow->notifierP = FALSE;
  249.     strcpy(aWindow->editDir, aWindow->dir);
  250.     Sx_EntryMake(wishDisplay, aWindow->titleWindow,
  251.         aWindow->surroundingWindow, "Directory:  ",
  252.         aWindow->titleFontPtr, aWindow->foreground, aWindow->background,
  253.         aWindow->editDir, sizeof (aWindow->editDir));
  254.  
  255.     return;
  256.     }
  257.  
  258.     /*
  259.      * Check validity of the new dir.  If it's no good, restore the name
  260.      * of the old dir in the title window.
  261.      */
  262.     if (lstat(aWindow->editDir, &dirAtts)
  263.         != 0) {
  264.     sprintf(wishErrorMsg,
  265.         "Cannot switch to dir %s.  Maybe it doesn't exist?",
  266.         aWindow->editDir);
  267.     aWindow->notifierP = TRUE;
  268.     Sx_Notify(wishDisplay, aWindow->surroundingWindow, -1, -1, 0,
  269.         wishErrorMsg, NULL, TRUE, "Skip command", (char *) NULL);
  270.     aWindow->notifierP = FALSE;
  271.     strcpy(aWindow->editDir, aWindow->dir);
  272.     Sx_EntryMake(wishDisplay, aWindow->titleWindow,
  273.         aWindow->surroundingWindow, "Directory:  ",
  274.         aWindow->titleFontPtr, aWindow->foreground, aWindow->background,
  275.         aWindow->editDir, sizeof (aWindow->editDir));
  276.  
  277.     return;
  278.     }
  279.     if ((dirAtts.st_mode & S_IFMT) != S_IFDIR) {    /* not a directory */
  280.     sprintf(wishErrorMsg, "%s is not a directory.", aWindow->editDir);
  281.     aWindow->notifierP = TRUE;
  282.     Sx_Notify(wishDisplay, aWindow->surroundingWindow, -1, -1, 0,
  283.         wishErrorMsg, NULL, TRUE, "Skip command", (char *) NULL);
  284.     aWindow->notifierP = FALSE;
  285.     strcpy(aWindow->editDir, aWindow->dir);
  286.     Sx_EntryMake(wishDisplay, aWindow->titleWindow,
  287.         aWindow->surroundingWindow, "Directory:  ",
  288.         aWindow->titleFontPtr, aWindow->foreground, aWindow->background,
  289.         aWindow->editDir, sizeof (aWindow->editDir));
  290.     return;
  291.     }
  292.  
  293.     WishChangeDir(aWindow, aWindow->editDir);
  294.  
  295.     return;
  296. }
  297.  
  298.  
  299. /*
  300.  *----------------------------------------------------------------------
  301.  *
  302.  * WishChangeDir --
  303.  *
  304.  *     Make the directory of the display be the given directory "where".
  305.  *    If the current directory has been chosen, ignore it since this
  306.  *    won't change anything.  The directory "where" must already have
  307.  *    been canonicalized and checked for existence.
  308.  *
  309.  * Results:
  310.  *    None.
  311.  *
  312.  * Side effects:
  313.  *    If a new directory was selected, it becomes the new diretory of the
  314.  *    display    and we rebuild the display.  The title window is updated to
  315.  *    show the new directory.
  316.  *
  317.  *----------------------------------------------------------------------
  318.  */
  319. void
  320. WishChangeDir(aWindow, where)
  321.     WishWindow    *aWindow;
  322.     char        *where;        /* Careful -- this parameter may
  323.                      * be aWindow->editDir */
  324. {
  325.     static char     *command = "insert cd";
  326.     char        *insertcommand;
  327.  
  328.     /* if the dir has not changed, just return */
  329.     if (strcmp(aWindow->dir, where) == 0) {
  330.     /* Just refresh titleWindow */
  331.     strcpy(aWindow->editDir, aWindow->dir);
  332.     Sx_EntryMake(wishDisplay, aWindow->titleWindow,
  333.         aWindow->surroundingWindow, "Directory:  ",
  334.         aWindow->titleFontPtr, aWindow->foreground, aWindow->background,
  335.         aWindow->editDir, sizeof (aWindow->editDir));
  336.     return;
  337.     }
  338.  
  339.     if (chdir(where) != 0) {
  340.     sprintf(wishErrorMsg, "Couldn't change directories to %s", where);
  341.     Sx_Panic(wishDisplay, wishErrorMsg);
  342.     }
  343.     if (!MonClient_ChangeDir(aWindow->dir, where)) {
  344.     sprintf(wishErrorMsg, "WishChangeDir: %s",
  345.         "Changing directories in file system monitor failed.");
  346.     Sx_Panic(wishDisplay, wishErrorMsg);
  347.     }
  348.  
  349.     strcpy(aWindow->dir, where);
  350.     /* Change the title to new dir */
  351.     strcpy(aWindow->editDir, aWindow->dir);
  352.     Sx_EntryMake(wishDisplay, aWindow->titleWindow,
  353.         aWindow->surroundingWindow, "Directory:  ",
  354.         aWindow->titleFontPtr, aWindow->foreground, aWindow->background,
  355.         aWindow->editDir, sizeof (aWindow->editDir));
  356.  
  357.     /* for window icon */
  358.     XStoreName(wishDisplay, aWindow->surroundingWindow, aWindow->dir); 
  359.  
  360.     WishGarbageCollect(aWindow);
  361.     /* delete old interpreter and start new one? */
  362.     strcpy(wishCurrentDirectory, aWindow->dir);
  363.  
  364.     WishSourceConfig(aWindow);
  365.  
  366.     aWindow->firstElement = 1;        /* start displaying from beginning */
  367.     WishSetPositions(aWindow);
  368.     /* WishRedraw will be called from event caused in WishSetPositions() */
  369.     /* throw a cd into tx window, if there is one.  +4 for space,'\n', & '\0' */
  370.     insertcommand = (char *) malloc(strlen(command) +
  371.         strlen(wishCurrentDirectory) + 4);
  372.     sprintf(insertcommand, "%s %s\\n", command, wishCurrentDirectory);
  373.     Tx_Command(wishDisplay, aWindow->txOutsideWindow, insertcommand);
  374.     free(insertcommand);
  375.  
  376.     return;
  377. }
  378.  
  379.  
  380. /*
  381.  *----------------------------------------------------------------------
  382.  *
  383.  * WishSourceConfig --
  384.  *
  385.  *     Source the config files to rebuild the display.
  386.  *
  387.  * Results:
  388.  *    None.
  389.  *
  390.  * Side effects:
  391.  *    After a redisplay, anything could be different.
  392.  *
  393.  *----------------------------------------------------------------------
  394.  */
  395. void
  396. WishSourceConfig(aWindow)
  397.     WishWindow    *aWindow;
  398. {
  399.     char    *environVar;
  400.     char    string[MAXPATHLEN];
  401.     struct    stat    attrs;
  402.     struct    stat    localAttrs;
  403.     FILE    *test1;
  404.     FILE    *test2;
  405.  
  406.     /*
  407.      * This prevents things that would change the display from doing so
  408.      * until a desired redraw event.
  409.      */
  410.     aWindow->dontDisplayChangesP = TRUE;
  411.     /*
  412.      * The implicit assumption here is that we always try to read a
  413.      * .wish file in the user's home directory.  Then we try to
  414.      * read one in the local directory, if it is different from the home
  415.      * directory.  The local one can override things in the home directory
  416.      * .wish file.  I find this awkward.  I think that it should look first for
  417.      * a local one and tbe local one could source the .wish in the home
  418.      * directory, if the user wishes.  But this is to keep wish compatible
  419.      * with mx and things.
  420.      */
  421.     environVar = (char *) getenv("HOME");
  422.     if (environVar != NULL) {
  423.     strcpy(string, environVar);
  424.     strcat(string, "/.wish");
  425. /*
  426.     sprintf(string, "%s/.wish", environVar);
  427. */
  428.     /*
  429.      * use open instead of access to test read permission with
  430.      * effictive, rather than real, uid.  How wasteful.
  431.      */
  432.     if ((test1 = fopen(string, "r")) != NULL) {
  433.         (void) stat(string, &attrs);
  434.         sprintf(string, "source %s/.wish", environVar);
  435.         (void) WishDoCmd(aWindow, string);
  436.         (void) fclose(test1);
  437.     }
  438.     }
  439.     /* Make sure we don't source the same file twice */
  440.     /* What if results of void'd WishDoCmd()'s were not TCL_OK? */
  441.  
  442.     /*
  443.      * use open instead of access to test read permission with
  444.      * effictive, rather than real, uid.  How wasteful.
  445.      */
  446.     if ((test2 = fopen(".wish", "r")) != NULL) {
  447.     (void) stat(".wish", &localAttrs);
  448.     if (attrs.st_ino != localAttrs.st_ino ||
  449.         attrs.st_dev != localAttrs.st_dev ||
  450.         attrs.st_serverID != localAttrs.st_serverID) {
  451.         (void) WishDoCmd(aWindow, "source .wish");
  452.     }
  453.     (void) fclose(test2);
  454.     }
  455.     /*
  456.      * If there wasn't a user startup file, get the defaults.
  457.      */
  458.     if (test1 == NULL && test2 == NULL) {
  459.     strcpy(string, wishStartUp);
  460.     strcat(string, "/.wish");
  461.     if ((test1 = fopen(string, "r")) != NULL) {
  462.         (void) stat(string, &attrs);
  463.         sprintf(string, "source %s/.wish", wishStartUp);
  464.         (void) WishDoCmd(aWindow, string);
  465.         (void) fclose(test1);
  466.     } else {
  467.         Sx_Panic(wishDisplay, "No .wish file found anywhere.  There should at least be one in the same directory as the wish executable.");
  468.     }
  469.     }
  470.  
  471.     /* If no groups from startup files, then get default "*" group. */
  472.     if (aWindow->groupList == NULL) {
  473.     if (WishGatherNames(aWindow) != TCL_OK) {
  474.         /* fix here too */
  475.     }
  476.     }
  477.  
  478.     /* now that we're finished sourcing the file, it's okay to update things. */
  479.     aWindow->dontDisplayChangesP = FALSE;
  480.  
  481.     return;
  482. }
  483.  
  484.  
  485.  
  486. /*
  487.  *----------------------------------------------------------------------
  488.  *
  489.  * WishHandleDrawingEvent --
  490.  *
  491.  *    Handle an event that requires drawing the display again.
  492.  *
  493.  * Results:
  494.  *    None.
  495.  *
  496.  * Side effects:
  497.  *    The display is drawn again.  If the window has changed size,
  498.  *    the diplay may be different.
  499.  *
  500.  *----------------------------------------------------------------------
  501.  */
  502. void
  503. WishHandleDrawingEvent(aWindow, eventPtr)
  504.     WishWindow    *aWindow;
  505.     XExposeEvent    *eventPtr;
  506. {
  507.     int    height, width, dummy1;
  508.     Window    dummy2;
  509.     char    buffer[100];
  510.  
  511.     /* ignore events from child windows */
  512.     if (eventPtr->window != aWindow->surroundingWindow && eventPtr->window !=
  513.         aWindow->displayWindow) {
  514.     return;
  515.     }
  516.     switch(eventPtr->type) {
  517.     /* This would only report a child resized, anyway, no? */
  518.     case ConfigureNotify:
  519.     case MapNotify:
  520.     XGetGeometry(wishDisplay, aWindow->displayWindow, &dummy2,
  521.         &dummy1, &dummy1, &width, &height, &dummy1, &dummy1);
  522.     if (width != aWindow->windowWidth || height != aWindow->windowHeight) {
  523.         sprintf(buffer, "resize %d %d", height, width);
  524.         (void) WishDoCmd(aWindow, buffer);
  525.         return;
  526.     }
  527.     strcpy(buffer, "redraw");
  528.     (void) WishDoCmd(aWindow, buffer);
  529.     return;
  530.     case Expose:
  531.     /*
  532.      * Only redraw on the last expose event.
  533.      */
  534.     if (eventPtr->count != 0) {
  535.         return;
  536.     }
  537.     strcpy(buffer, "redraw");
  538.     (void) WishDoCmd(aWindow, buffer);
  539.     return;
  540.     default:
  541.     return;
  542.     }
  543. }
  544.  
  545.  
  546.  
  547. /*
  548.  *----------------------------------------------------------------------
  549.  *
  550.  * WishHandleDestructionEvent --
  551.  *
  552.  *    Not yet implemented.  Should do garbage collection and such
  553.  *    once I have got that in place.
  554.  *
  555.  * Results:
  556.  *    None.
  557.  *
  558.  * Side effects:
  559.  *    None.
  560.  *
  561.  *----------------------------------------------------------------------
  562.  */
  563. /*ARGSUSED*/
  564. void
  565. WishHandleDestructionEvent(aWindow, eventPtr)
  566.     WishWindow    *aWindow;
  567.     XExposeEvent    *eventPtr;
  568. {
  569.     return;
  570. }
  571.  
  572.  
  573. /*
  574.  *----------------------------------------------------------------------
  575.  *
  576.  * WishMouseEvent --
  577.  *
  578.  *    This routine implements the bindings of various mouse
  579.  *    buttons to various commands.  This routine is temporary and will
  580.  *    go away when the command bindings stuff is done.
  581.  *
  582.  * Results:
  583.  *    None.
  584.  *
  585.  * Side effects:
  586.  *    If a command was chosen, it is executed.
  587.  *
  588.  *----------------------------------------------------------------------
  589.  */
  590. void
  591. WishMouseEvent(window, eventPtr)
  592.     Window        window;        /* the surrounding window */
  593.     XButtonEvent    *eventPtr;
  594. {
  595.     static    int    lastWindow = 0;
  596.     static    int    lastTime = 0;
  597.     static    int    repeatCount = 0;
  598.     static    int    lastX = -1;
  599.     static    int    lastY = -1;
  600.     int        x, y;
  601.     WishFile    *filePtr;
  602.     WishGroup    *groupPtr;
  603.     WishWindow    *aWindow;
  604.     int        button = 0;
  605.     char    *selectButton = NULL;
  606.     char    *command;
  607.     char    buffer[100];
  608.  
  609.  
  610. #define    DETAIL_MASK    7
  611.  
  612.     if (eventPtr->subwindow != NULL) {
  613.     return;
  614.     }
  615.     switch (eventPtr->type) {
  616.     case MotionNotify:
  617.     case LeaveNotify:
  618.     /* Highlight mouse movement */
  619.     WishHighlightMovement(window, eventPtr);
  620.     return;
  621.     case ButtonPress:
  622.     break;
  623.     default:
  624.     return;
  625.     }
  626.     /* Left button is Button1? */
  627.     if ((eventPtr->button & DETAIL_MASK) == Button1) {
  628.     button |= WISH_LEFT_BUTTON;
  629.     }
  630.     if ((eventPtr->button & DETAIL_MASK) == Button2) {
  631.     button |= WISH_MIDDLE_BUTTON;
  632.     }
  633.     if ((eventPtr->button & DETAIL_MASK) == Button3) {
  634.     button |= WISH_RIGHT_BUTTON;
  635.     }
  636.     /* What to do about meta, shift and double buttons??? */
  637.  
  638.     /*
  639.      * See which group, if any, button is over.  See if it matches a
  640.      * button binding for that group.  If not, see if it matches
  641.      * the selection button.
  642.      */
  643.     
  644.     /* the event was selected in the display window, so coordinates are ok */
  645.     x = ((XButtonEvent *) eventPtr)->x;
  646.     y = ((XButtonEvent *) eventPtr)->y;
  647.  
  648.     if (XFindContext(wishDisplay, window, wishWindowContext,
  649.         (caddr_t) &aWindow) != 0) {
  650.     Sx_Panic(wishDisplay, "Wish didn't recognize given window.");
  651.     }
  652.     filePtr = WishMapCoordsToFile(aWindow, x, y);
  653.     if (filePtr != NULL) {
  654.     groupPtr = filePtr->myGroupPtr;
  655.     command = WishGetGroupBinding(groupPtr, button);
  656.     if (command != NULL) {
  657.         Tcl_SetVar(aWindow->interp, "pointed", filePtr->name, 1);
  658.         /* do it */
  659.         (void) WishDoCmd(aWindow, command);
  660.     }
  661.     }
  662.     /* No command, see if selection was meant */
  663.     
  664.     
  665.     /*
  666.      * See if button matches selection button.
  667.      * What do I do about meta's and shifts and such???
  668.      */
  669.     selectButton = Tcl_GetVar(aWindow->interp, "selectionButton", 1);
  670.     if (selectButton == NULL || selectButton[0] == '\0') {
  671.     Tcl_SetVar(aWindow->interp, "selectionButton", "left", 1);
  672.     if (button != WISH_LEFT_BUTTON) {    /* not selection */
  673.         return;
  674.     }
  675.     } else {
  676.     if (button != WishWhichButton(selectButton)) {    /* not select.*/
  677.         return;
  678.     }
  679.     }
  680.  
  681.     /* Prof. Ousterhout does drag scrolling here if the shift key is down */
  682.  
  683.     /* Count the number of clicks in the same place. */
  684.     if (lastWindow == window && ((eventPtr->time - lastTime) < 50) &&
  685.         ((lastX + 2) >= eventPtr->x) && ((lastX - 2) <= eventPtr->x) &&
  686.         ((lastY + 2) >= eventPtr->y) && ((lastY - 2) <= eventPtr->y)) {
  687.     repeatCount += 1;
  688.     if (repeatCount > 2) {
  689.         repeatCount = 1;
  690.     }
  691.     } else {
  692.     repeatCount = 1;
  693.     }
  694.     lastX = eventPtr->x;
  695.     lastY = eventPtr->y;
  696.     lastTime = eventPtr->time;
  697.     lastWindow = window;
  698.     switch (repeatCount) {
  699.     case 2:
  700.     /* select line */
  701.     sprintf(buffer, "toggleSelection %d %d 1", x, y);
  702.     (void) WishDoCmd(aWindow, buffer);
  703. /*    old...
  704.     WishToggleSelection(window, eventPtr, TRUE);
  705.  */
  706.     break;
  707.     default:
  708.     /* select filename */
  709.     sprintf(buffer, "toggleSelection %d %d 0", x, y);
  710.     (void) WishDoCmd(aWindow, buffer);
  711. /*    old...
  712.     WishToggleSelection(window, eventPtr, FALSE);
  713.  */
  714.     break;
  715.     }
  716.     return;
  717. }
  718.  
  719.  
  720. /*
  721.  *----------------------------------------------------------------------
  722.  *
  723.  * WishHandleEnterEvent --
  724.  *
  725.  *    The mouse has entered a window.  Make sure that the current directory
  726.  *    of the program is the directory of that window.
  727.  *
  728.  * Results:
  729.  *    None.
  730.  *
  731.  * Side effects:
  732.  *    The current directory of the program will change to that of the
  733.  *    window, if it is different.
  734.  *
  735.  *----------------------------------------------------------------------
  736.  */
  737. void
  738. WishHandleEnterEvent(aWindow, eventPtr)
  739.     WishWindow    *aWindow;
  740.     XEnterWindowEvent    *eventPtr;
  741. {
  742.     if (eventPtr->type != EnterNotify) {
  743.     return;
  744.     }
  745.     if (strcmp(wishCurrentDirectory, aWindow->dir) == 0) {
  746.     return;
  747.     }
  748.     if (chdir(aWindow->dir) != 0) {
  749.     sprintf(wishErrorMsg, "%s %s.  %s %s",
  750.         "Couldn't change back to directory", aWindow->dir,
  751.         "Does it still exist?  This window no longer makes sense",
  752.         "and will now disappear.");
  753.     aWindow->notifierP = TRUE;
  754.     Sx_Notify(wishDisplay, aWindow->displayWindow, -1, -1, 0,
  755.         wishErrorMsg, NULL, TRUE, "Continue", NULL);
  756.     aWindow->notifierP = FALSE;
  757.     (void) WishDoCmd(aWindow, "close");
  758.     return;
  759.     }
  760.     strcpy(wishCurrentDirectory, aWindow->dir);
  761.  
  762.     return;
  763. }
  764.  
  765.  
  766.  
  767. /*
  768.  *----------------------------------------------------------------------
  769.  *
  770.  * WishKeyProc --
  771.  *
  772.  *    This procedure is invoked by the Sx dispatcher whenever a
  773.  *    key is typed in an Wish window.
  774.  *
  775.  * Results:
  776.  *    None.
  777.  *
  778.  * Side effects:
  779.  *    Can be almost arbitrary.  Depends completely on the key.
  780.  *
  781.  *----------------------------------------------------------------------
  782.  */
  783. void
  784. WishKeyProc(aWindow, eventPtr)
  785.     WishWindow    *aWindow;    /* Keeps track of information for
  786.                      * window. */
  787.     XKeyEvent *eventPtr;        /* Describes key that was pressed. */
  788. {
  789.     char    keyString[20];
  790.     char    *command, *mapping;
  791.     register    char    c;
  792.     int        result, nBytes;
  793.     char    insertCommand[20];
  794.     Window    w;
  795.  
  796.     w = aWindow->surroundingWindow;
  797.     if (eventPtr->subwindow != NULL) {
  798. fprintf(stderr, "WishKeyProc w = %d, eventPtr->subwindow == %d\n", w, eventPtr->subwindow);
  799.     return;
  800.     }
  801.  
  802.     /*
  803.      * Convert from raw key number to its ASCII equivalent, then pass
  804.      * each equivalent character to the keystroke binder.  Process
  805.      * any commands that are matched this way.
  806.      */
  807.     
  808.     nBytes = XLookupString(eventPtr, keyString, 20, (KeySym *) NULL,
  809.         (XComposeStatus *) NULL);
  810.     /* John does stuff here to force ctrl chars and meta bits.  Should I? */
  811.     for (mapping = keyString; nBytes > 0; nBytes--, mapping++) {
  812.     result = Cmd_MapKey(aWindow->cmdTable, *mapping, &command);
  813.     if (result == CMD_PARTIAL) {
  814.         continue;
  815.     } else if (result == CMD_UNBOUND) {
  816.         char    msg[30];
  817.  
  818.         WishCvtToPrintable(command, 30, msg);
  819. #ifdef NOTDEF
  820.         if (aWindow->msgWindow != NULL) {
  821. #endif NOTDEF
  822.         sprintf(wishErrorMsg,
  823.             "The keystroke sequence \"%s\" has no function.", msg);
  824.         aWindow->notifierP = TRUE;
  825.         Sx_Notify(wishDisplay, w, -1, -1, 0, wishErrorMsg,
  826.             aWindow->fontPtr, TRUE, "Continue", (char *) NULL);
  827.         aWindow->notifierP = FALSE;
  828.         return;
  829. #ifdef NOTDEF
  830.         } else {
  831.         sprintf(wishErrorMsg,
  832.             "The keystroke sequence\n\"%s\"\nhas no function.",
  833.             msg);
  834.         aWindow->notifierP = TRUE;
  835.         (void) Sx_Notify(wishDisplay, aWindow->surroundingWindow,
  836.             -1, -1, 0, wishErrorMsg, aWindow->fontPtr, TRUE,
  837.             "Ignore and go on", NULL);
  838.         aWindow->notifierP = FALSE;
  839.         }
  840.         break;
  841. #endif NOTDEF
  842.     } else if (result == CMD_OK) {
  843.         if (*command == '!') {
  844.         command++;
  845.         } else {
  846. #ifdef NOTDEF
  847.         Undo_Mark(aWindow->fileInfoPtr->log);
  848. #endif NOTDEF
  849.         }
  850.  
  851.         /*
  852.          * If the command is "@", then generate an insert command for
  853.          * the last character typed.
  854.          */
  855.  
  856.         if ((command[0] == '@') && (command[1] == 0)) {
  857.         c = *mapping;
  858.         if (isprint(c) && !isspace(c) && (c != '\\')
  859.             && (c != '"') && (c != ';') && (c != '$')) {
  860.             sprintf(insertCommand, "ins %c", c);
  861.         } else {
  862.             int i = c & 0xff;
  863.  
  864.             sprintf(insertCommand, "ins \\%o", i);
  865.         }
  866.         command = insertCommand;
  867.         }
  868.  
  869.         (void) WishDoCmd(aWindow, command);
  870. #ifdef NOTDEF
  871.  
  872.         /*
  873.          * Watch out!  The command could have destroyed the window.
  874.          */
  875.     
  876.         if (MxGetMxWindow(w) != aWindow) {
  877.         return;
  878.         }
  879. #endif NOTDEF
  880.     }
  881.     }
  882. }
  883.  
  884.  
  885.  
  886. /*
  887.  *----------------------------------------------------------------------
  888.  *
  889.  * WishHandleMonitorUpdates --
  890.  *
  891.  *    This routine should be called whenever the monitor informs us
  892.  *    that a change has occured in a directory we are viewing.
  893.  *    Note that the directory-changing code here is almost identical to
  894.  *    that in WishHandlerEnterEvent().  This means I should have
  895.  *    it as a separate routine, soon.
  896.  *
  897.  * Results:
  898.  *    None.
  899.  *
  900.  * Side effects:
  901.  *    The given window will be updated.
  902.  *
  903.  *----------------------------------------------------------------------
  904.  */
  905. void
  906. WishHandleMonitorUpdates()
  907. {
  908.     int    windowID;
  909.     int    cc;
  910.     char    *ptr;
  911.     int        numbytes;
  912.     WishWindow    *aWindow;
  913.     int        firstElement;
  914. #ifdef MON_DEBUG
  915.     char    buffer[MAXPATHLEN + 1];
  916. #endif MON_DEBUG
  917.  
  918.     ptr = (char *) (&windowID);
  919.     numbytes = sizeof (windowID);
  920.     cc = 0;
  921.     for ( ; cc != -1 && cc < numbytes; numbytes -= cc, ptr += cc) {
  922.     cc = read(monClient_ReadPort, ptr, numbytes);
  923.     }
  924.     if (cc == -1) {
  925.     perror("WishHandleMonitorUpdates, windowID read: ");
  926.     exit(1);
  927.     }
  928.  
  929. #ifdef MON_DEBUG
  930.     ptr = buffer;
  931.     numbytes = sizeof (buffer);
  932.     cc = 0;
  933.     for ( ; cc != -1 && cc < numbytes ; numbytes -= cc, ptr += cc) {
  934.     cc = read(monClient_ReadPort, ptr, numbytes);
  935.     if (*(ptr + cc - 1) == '\0') {
  936.         /* came to end of string */
  937.         break;
  938.     }
  939.     }
  940.     if (cc == -1) {
  941.     perror("WishHandleMonitorUpdates, path read: ");
  942.     exit(1);
  943.     }
  944. #endif MON_DEBUG
  945.  
  946.     if (XFindContext(wishDisplay, windowID, wishWindowContext,
  947.         (caddr_t) &aWindow) != 0) {
  948.     Sx_Panic(wishDisplay, "Wish didn't recognize given window.");
  949.     }
  950.     /*
  951.      * leave aWindow->firstElement the same so that scrolling and such
  952.      * doesn't change.  Later, worry about selection changing.  Also,
  953.      * make sure we're in the same directory as the window we are redoing.
  954.      */
  955.     if (strcmp(wishCurrentDirectory, aWindow->dir) != 0) {
  956.     if (chdir(aWindow->dir) != 0) {
  957.         sprintf(wishErrorMsg, "%s %s.  %s %s",
  958.             "Couldn't change back to directory", aWindow->dir,
  959.             "Does it still exist?  This window no longer makes",
  960.             "sense and will now disappear.");
  961.         aWindow->notifierP = TRUE;
  962.         Sx_Notify(wishDisplay, aWindow->displayWindow, -1, -1, 0,
  963.             wishErrorMsg, NULL, TRUE, "Continue", NULL);
  964.         aWindow->notifierP = FALSE;
  965.         (void) WishDoCmd(aWindow, "close");
  966.         return;
  967.     }
  968.     strcpy(wishCurrentDirectory, aWindow->dir);
  969.     }
  970.     firstElement = aWindow->firstElement;
  971.     WishGarbageCollect(aWindow);
  972.     WishSourceConfig(aWindow);
  973.     aWindow->firstElement = firstElement;
  974.     WishSetPositions(aWindow);
  975.     /* WishRedraw will be called from event caused in WishSetPositions() */
  976.  
  977.     return;
  978. }
  979.